package com.icongyou.enterprise.talent_analysis.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.icongyou.enterprise.common.exception.BusinessException;
import com.icongyou.enterprise.talent_analysis.entity.PortraitTemplate;
import com.icongyou.enterprise.talent_analysis.entity.dto.PortraitTemplateCreateRequest;
import com.icongyou.enterprise.talent_analysis.entity.dto.PortraitTemplateDTO;
import com.icongyou.enterprise.talent_analysis.entity.template.TemplateDimension;
import com.icongyou.enterprise.talent_analysis.entity.template.TemplateMetricMapping;
import com.icongyou.enterprise.talent_analysis.mapper.HrTemplatePreferenceMapper;
import com.icongyou.enterprise.talent_analysis.mapper.PortraitTemplateMapper;
import com.icongyou.enterprise.talent_analysis.service.impl.PortraitTemplateServiceImpl;
import com.icongyou.enterprise.talent_analysis.service.support.TemplateDimensionAutoFiller;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

/**
 * 画像模板服务测试
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("画像模板服务测试")
class PortraitTemplateServiceImplTest {

    @Mock
    private PortraitTemplateMapper portraitTemplateMapper;

    @Mock
    private HrTemplatePreferenceMapper preferenceMapper;

    @Mock
    private PortraitAsyncService portraitAsyncService;

    private PortraitTemplateServiceImpl service;
    private TemplateDimensionAutoFiller dimensionAutoFiller;
    private ObjectMapper objectMapper;

    @BeforeEach
    void setUp() {
        dimensionAutoFiller = new TemplateDimensionAutoFiller();
        objectMapper = new ObjectMapper();
        service = new PortraitTemplateServiceImpl(
            portraitTemplateMapper,
            preferenceMapper,
            dimensionAutoFiller,
            objectMapper,
            portraitAsyncService
        );
    }

    @Test
    @DisplayName("创建模板 - 成功场景")
    void testCreateTemplate_Success() {
        // Arrange
        PortraitTemplateCreateRequest request = createValidRequest();
        request.setActive(true);
        
        when(portraitTemplateMapper.countByCreatedBy(anyString())).thenReturn(0);
        when(portraitTemplateMapper.insert(any(PortraitTemplate.class))).thenReturn(1);

        // Act
        PortraitTemplateDTO result = service.createTemplate(request);

        // Assert
        assertNotNull(result);
        assertEquals(request.getTemplateName(), result.getTemplateName());
        assertEquals(6, result.getDimensions().size());
        
        // 验证清除了企业的其他激活模板
        verify(portraitTemplateMapper).clearActiveFlag(request.getEnterpriseId());
        verify(portraitTemplateMapper).insert(any(PortraitTemplate.class));
        verify(portraitAsyncService).triggerBatchUpdate(anyString(), eq("TEMPLATE_CREATED"));
    }

    @Test
    @DisplayName("创建模板 - 超出限制应抛出异常")
    void testCreateTemplate_ExceedsLimit_ThrowsException() {
        // Arrange
        PortraitTemplateCreateRequest request = createValidRequest();
        when(portraitTemplateMapper.countByCreatedBy(anyString())).thenReturn(2);

        // Act & Assert
        BusinessException exception = assertThrows(
            BusinessException.class,
            () -> service.createTemplate(request)
        );
        assertTrue(exception.getMessage().contains("最多只能创建2个模板"));
        
        verify(portraitTemplateMapper, never()).insert(any());
    }

    @Test
    @DisplayName("创建模板 - 维度数量不足应抛出异常")
    void testCreateTemplate_InvalidDimensionCount_ThrowsException() {
        // Arrange
        PortraitTemplateCreateRequest request = createValidRequest();
        request.setDimensions(new ArrayList<>()); // 空维度列表
        
        when(portraitTemplateMapper.countByCreatedBy(anyString())).thenReturn(0);

        // Act & Assert
        BusinessException exception = assertThrows(
            BusinessException.class,
            () -> service.createTemplate(request)
        );
        assertTrue(exception.getMessage().contains("必须包含"));
    }

    @Test
    @DisplayName("创建模板 - 自动填充预设指标")
    void testCreateTemplate_AutoFillMetrics() {
        // Arrange
        PortraitTemplateCreateRequest request = createValidRequest();
        // 将第一个维度的指标设置为null，系统应该能够自动填充
        request.getDimensions().get(0).setMetrics(null);
        
        when(portraitTemplateMapper.countByCreatedBy(anyString())).thenReturn(0);
        when(portraitTemplateMapper.insert(any(PortraitTemplate.class))).thenReturn(1);

        // Act
        PortraitTemplateDTO result = service.createTemplate(request);

        // Assert
        assertNotNull(result);
        // 验证第一个维度的指标已被自动填充
        assertTrue(result.getDimensions().get(0).getMetrics().size() > 0);
        // 验证其他维度保留了用户提供的指标
        assertEquals(1, result.getDimensions().get(1).getMetrics().size());
    }

    @Test
    @DisplayName("创建模板 - 无法自动填充时抛出异常")
    void testCreateTemplate_CannotAutoFill_ThrowsException() {
        // Arrange
        PortraitTemplateCreateRequest request = createValidRequest();
        // 使用未知维度代码,无法自动填充
        TemplateDimension unknownDim = new TemplateDimension();
        unknownDim.setCode("UNKNOWN_CODE");
        unknownDim.setName("未知维度");
        unknownDim.setWeight(1.0);
        unknownDim.setMetrics(Collections.emptyList());
        request.getDimensions().set(0, unknownDim);
        
        when(portraitTemplateMapper.countByCreatedBy(anyString())).thenReturn(0);

        // Act & Assert
        BusinessException exception = assertThrows(
            BusinessException.class,
            () -> service.createTemplate(request)
        );
        assertTrue(exception.getMessage().contains("指标缺失"));
    }

    @Test
    @DisplayName("获取模板 - 成功解析JSON")
    void testGetTemplate_Success() {
        // Arrange
        PortraitTemplate entity = createTemplateEntity();
        when(portraitTemplateMapper.selectById("template-1")).thenReturn(entity);

        // Act
        PortraitTemplateDTO result = service.getTemplate("template-1");

        // Assert
        assertNotNull(result);
        assertEquals("template-1", result.getId());
        assertEquals("测试模板", result.getTemplateName());
        assertNotNull(result.getDimensions());
    }

    @Test
    @DisplayName("获取模板 - 模板不存在应抛出异常")
    void testGetTemplate_NotFound_ThrowsException() {
        // Arrange
        when(portraitTemplateMapper.selectById("nonexistent")).thenReturn(null);

        // Act & Assert
        BusinessException exception = assertThrows(
            BusinessException.class,
            () -> service.getTemplate("nonexistent")
        );
        assertTrue(exception.getMessage().contains("不存在"));
    }

    @Test
    @DisplayName("更新模板 - 成功场景")
    void testUpdateTemplate_Success() {
        // Arrange
        PortraitTemplateDTO request = new PortraitTemplateDTO();
        request.setId("template-1");
        request.setTemplateName("更新后的模板");
        request.setDescription("更新后的描述");
        request.setDimensions(createValidDimensions());
        request.setActive(true);

        PortraitTemplate existing = createTemplateEntity();
        when(portraitTemplateMapper.selectById("template-1")).thenReturn(existing);
        when(portraitTemplateMapper.updateById(any(PortraitTemplate.class))).thenReturn(1);

        // Act
        PortraitTemplateDTO result = service.updateTemplate("template-1", request);

        // Assert
        assertNotNull(result);
        assertEquals("更新后的模板", result.getTemplateName());
        
        ArgumentCaptor<PortraitTemplate> captor = ArgumentCaptor.forClass(PortraitTemplate.class);
        verify(portraitTemplateMapper).updateById(captor.capture());
        assertEquals("更新后的模板", captor.getValue().getTemplateName());
    }

    @Test
    @DisplayName("删除模板 - 成功场景")
    void testDeleteTemplate_Success() {
        // Arrange
        PortraitTemplate entity = createTemplateEntity();
        when(portraitTemplateMapper.selectById("template-1")).thenReturn(entity);
        when(portraitTemplateMapper.deleteById("template-1")).thenReturn(1);

        // Act & Assert
        assertDoesNotThrow(() -> service.deleteTemplate("template-1"));
        
        verify(portraitTemplateMapper).deleteById("template-1");
    }

    @Test
    @DisplayName("获取企业模板列表 - 成功场景")
    void testListTemplates_Success() {
        // Arrange
        String enterpriseId = "enterprise-1";
        List<PortraitTemplate> templates = List.of(
            createTemplateEntity(),
            createTemplateEntity()
        );
        when(portraitTemplateMapper.selectByEnterprise(enterpriseId, null))
            .thenReturn(templates);

        // Act
        List<PortraitTemplateDTO> result = service.listTemplates(enterpriseId, null);

        // Assert
        assertNotNull(result);
        assertEquals(2, result.size());
    }

    // ==================== Helper Methods ====================

    private PortraitTemplateCreateRequest createValidRequest() {
        PortraitTemplateCreateRequest request = new PortraitTemplateCreateRequest();
        request.setEnterpriseId("enterprise-1");
        request.setTemplateName("测试模板");
        request.setDescription("测试描述");
        request.setActive(false);
        request.setAiSuggested(false);
        request.setCreatedBy("hr-user-1");
        request.setDimensions(createValidDimensions());
        return request;
    }

    private List<TemplateDimension> createValidDimensions() {
        List<TemplateDimension> dimensions = new ArrayList<>();
        String[] codes = {"TECH", "PROBLEM_SOLVING", "LEARNING", "COLLABORATION", "COMMUNICATION", "EXECUTION"};
        String[] names = {"技术能力", "问题解决", "学习能力", "团队协作", "沟通能力", "执行能力"};
        
        for (int i = 0; i < 6; i++) {
            TemplateDimension dim = new TemplateDimension();
            dim.setCode(codes[i]);
            dim.setName(names[i]);
            dim.setWeight(1.0);
            
            TemplateMetricMapping metric = new TemplateMetricMapping();
            metric.setMetricKey("metric_" + i);
            metric.setWeight(1.0);
            dim.setMetrics(List.of(metric));
            
            dimensions.add(dim);
        }
        return dimensions;
    }

    private PortraitTemplate createTemplateEntity() {
        PortraitTemplate entity = new PortraitTemplate();
        entity.setId("template-1");
        entity.setEnterpriseId("enterprise-1");
        entity.setTemplateName("测试模板");
        entity.setDescription("测试描述");
        entity.setDimensionsJson("[{\"code\":\"TECH\",\"name\":\"技术能力\",\"weight\":1.0,\"metrics\":[{\"metricKey\":\"avg_course_score\",\"weight\":0.6}]}]");
        entity.setActive(true);
        entity.setAiSuggested(false);
        entity.setCreatedBy("hr-user-1");
        entity.setCreatedAt(LocalDateTime.now());
        entity.setUpdatedAt(LocalDateTime.now());
        return entity;
    }
}
